/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import fs from "fs";
import path from "path";
import { globSync } from 'glob';
import Logger, { LogLevel } from "./logger";

class AbortOptions {
    onConvertError: boolean;
    onScanError: boolean;
}

const consoleLogger = Logger.getConsoleLogger();
export class SRConfig {
    private logFilePath: string;
    // Log level
    private logLevel: LogLevel;
    // Indicate if put generated files' name to .gitignore
    private addNewFileToGitIgnore: boolean = false;
    // Target files paths or file names with absolute path
    private targetFiles: string[] = [];
    // Error occurs when import external ets file which is not with prefix in extraImportPrefixes
    private extraImportPrefixes: string[] = [];
    // copy imports path
    private copyImportPrefixes:string[] = [];
    // DevEco project path
    private projectPath: string;
    // Transformer tool will abort when error occurs during convert and scan period by default
    private abortOptions: AbortOptions = {onConvertError: true, onScanError: true};
    // absolute path of ttsconfig.json5
    private ttsConfigJsonPath: string;

    constructor() {

    }

    configure(logLevel: string, addNewFileToGitIgnore: boolean = false, targetFiles: string[] = [], ttsConfigJsonPath: string) {
        this.logLevel = LogLevel[logLevel as LogLevel]??LogLevel['WARN'];
        Logger.configure(this.logFilePath, this.logLevel);
        this.projectPath = path.resolve(path.dirname(ttsConfigJsonPath), '..');
        this.addNewFileToGitIgnore = addNewFileToGitIgnore;
        this.targetFiles = globSync(targetFiles, {cwd: path.parse(ttsConfigJsonPath).dir, posix: true, dotRelative: true})
            .filter(p => !p.startsWith("./oh_modules") && !p.startsWith("./node_modules") && !p.startsWith("./build"))
            .map(p => path.parse(ttsConfigJsonPath).dir + path.sep + path.normalize(p));
        this.ttsConfigJsonPath = ttsConfigJsonPath;
    }

    public buildFromJson(ttsConfigJsonPath: string): boolean {
        if (fs.existsSync(ttsConfigJsonPath)) {
            const ttsConfigText = fs.readFileSync(ttsConfigJsonPath, "utf8");
            const ttsConfig = JSON.parse(ttsConfigText);
            const logLevel: string = ttsConfig.logLevel?? 'WARN';
            const addNewFileToGitIgnore: boolean = ttsConfig.addGeneratedFilesIntoGitIgnore?? false;
            this.logFilePath = ttsConfig.logFilePath?? './out/SRCodeGen.log';
            const targetFiles: string[] = ttsConfig.targetFiles?? [];
            if (ttsConfig.abortOptions) {
                this.abortOptions.onConvertError = ttsConfig.abortOptions.onConvertError;
                this.abortOptions.onScanError = ttsConfig.abortOptions.onScanError;
            }
            this.extraImportPrefixes = ttsConfig.extraImportPrefixes?? [];
            this.copyImportPrefixes = ttsConfig.copyImportPrefixes?? [];
            this.configure(logLevel.toUpperCase(), addNewFileToGitIgnore, targetFiles, ttsConfigJsonPath);

            // After log system setup, use consoleLogger
            consoleLogger.info(`Found ${this.targetFiles.length} tts files...`);
            consoleLogger.info(`log file path: ${this.logFilePath}`);
            return true;
        } else {
            console.error(`Your ttsConfigJsonPath: "${ttsConfigJsonPath}" is not exist.`);
            return false;
        }
    }

    needAddNewFileToGitIgnore(): boolean {
        return this.addNewFileToGitIgnore;
    }

    getLogLevel(): LogLevel {
        return this.logLevel;
    }

    getTargetFiles(): string[] {
        return this.targetFiles;
    }

    getProjectPath(): string {
        return this.projectPath;
    }

    isAbortOnConvertError(): boolean {
        return this.abortOptions.onConvertError;
    }

    isAbortOnScanError(): boolean {
        return this.abortOptions.onScanError;
    }

    getExtraImportPrefixes(): string[] {
        return this.extraImportPrefixes;
    }

    getCopyImportPrefixes(): string[] {
        return this.copyImportPrefixes;
    }

    getTtsConfigJsonPath(): string {
        return this.ttsConfigJsonPath;
    }

    getLogFilePath(): string {
        return this.logFilePath;
    }
}